﻿#region Directives

using ConnectIntegrationHub.WebService.Common;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Crm.Services.Utility;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using System;
using System.ServiceModel.Description;

#endregion Directives

namespace ConnectIntegrationHub.WebService.CRM
{
    public class Configuration
    {
        #region Enumerations

        public enum InstallationTypes
        {
            OnPremise = 1,
            OnLine = 2
        }
 
        #endregion Enumerations

        #region Properties

        public Guid Id
        {
            get;
            set;
        }

        public Guid? ApplicationId
        {
            get;
            set;
        }

        public InstallationTypes InstallationType
        {
            get;
            set;
        }

        public String Name
        {
            get;
            set;
        }

        public String UserName
        {
            get;
            set;
        }

        public String Password
        {
            get;
            set;
        }

        public String OrganizationUri
        {
            get;
            set;
        }

        public String HomeUri
        {
            get;
            set;
        }

        public IOrganizationService Service
        {
            get
            {
                if (_Service == null)
                {
                    _Service = getInternalService();
                }
                return _Service;
            }
            set
            {
                _Service = value;
            }
        }
        
        #endregion Properties

        #region Fields
        
        private IOrganizationService _Service = null;
        
        #endregion Fields

        #region Constructors

        public Configuration(Guid id, String name, InstallationTypes installationType, String organizationUri, Guid? applicationId, String userName, String password)
        {
            this.Id = id;
            this.Name = name;
            this.InstallationType = installationType;
            this.OrganizationUri = organizationUri;

            this.ApplicationId = applicationId;
            this.UserName = userName;
            this.Password = password;
            
            this.setService();
        }

        #endregion Constructors

        #region Public Methods
        
        public void setService()
        {
            _Service = this.getInternalService();
        }

        #endregion Public Methods

        #region Private Methods
        
        private ClientCredentials getClientCredentials()
        {
            ClientCredentials result = new ClientCredentials();

            result.UserName.UserName = this.UserName;
            result.UserName.Password = this.Password;
            
            return result;
        }

        private IOrganizationService getInternalService()
        {
            if (this.OrganizationUri.IsNullOrEmpty())
            {
                return null;
            }

            IOrganizationService result = null;
            Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy _serviceProxy = null;

            var clientCredentials = this.getClientCredentials();
            ClientCredentials deviceCredentials = null;

            if (this.InstallationType == InstallationTypes.OnLine)
            {
                try
                {
                    deviceCredentials = DeviceIdManager.LoadOrRegisterDevice(clientCredentials.UserName.UserName, clientCredentials.UserName.Password);
                }
                catch
                {
                }

                if (deviceCredentials == null)
                {
                    try
                    {
                        deviceCredentials = DeviceIdManager.LoadDeviceCredentials();
                    }
                    catch { }
                }

                if (deviceCredentials == null && this.ApplicationId.HasValue)
                {
                    try
                    {
                        deviceCredentials = DeviceIdManager.RegisterDevice(this.ApplicationId.Value);
                    }
                    catch { }
                }
            }

            Uri homeUri = null;
            if (!String.IsNullOrEmpty(this.HomeUri))
            {
                homeUri = new Uri(this.HomeUri);
            }

            String apiUri = this.OrganizationUri.Replace(".crm.", ".api.crm.");
            _serviceProxy = new OrganizationServiceProxy(new Uri(apiUri + "/XRMServices/2011/Organization.svc"), homeUri, clientCredentials, deviceCredentials);

            result = _serviceProxy as IOrganizationService;
            WhoAmIResponse response = result.Execute(new WhoAmIRequest()) as WhoAmIResponse;
            _serviceProxy.Authenticate();

            _serviceProxy.Timeout = new TimeSpan(1, 0, 0, 0);

            return result;
        }

        #endregion Private Methods        

        #region Public Static Methods

        #endregion Public Static Methods
    }
}